﻿Imports System.Drawing.Imaging
Public Class DataConverter
	Private Const ByteJump_Short As Integer = 2
	Private Const ByteJump_Long As Integer = 4
	Private Const ByteJump_Rational As Integer = 8
	Private Const ByteJump_SLong As Integer = 4
	Private Const ByteJump_SRational As Integer = 8

	Private Const DoubleType_Format As String = "0.0####"

	Public Enum FormatInstr
		''' <summary>
		''' No formatting instruction
		''' </summary>
		''' <remarks></remarks>
		No_Op

		''' <summary>
		''' Instruction to change the value to a fraction.
		''' </summary>
		''' <remarks>This is only applicable to RATIONAL and SRATIONAL tags.</remarks>
		Fraction

		''' <summary>
		''' Instruction to format the bytes as a non-null terminated string.
		''' </summary>
		''' <remarks>This is only applicable to UNDEFINED tags.</remarks>
		AllChar

		''' <summary>
		''' Instruction to format the bytes as a Base-64 string.
		''' </summary>
		''' <remarks>This is only applicable to BYTE tags.</remarks>
		Base64
	End Enum
	''' <summary>
	''' Format a Byte tag.
	''' </summary>
	''' <param name="propItem"></param>
	''' <param name="formatInstr"></param>
	''' <returns></returns>
	''' <remarks></remarks>
	Function FormatTagByte(ByVal propItem As PropertyItem, ByVal formatInstr As FormatInstr) As String
		Dim strRet As String

		If (formatInstr = formatInstr.Base64) Then
			strRet = Convert.ToBase64String(propItem.Value)
		Else
			strRet = BitConverter.ToString(propItem.Value, 0, propItem.Len)
		End If
		Return strRet
	End Function
	''' <summary>
	''' Format an ASCII tag.
	''' </summary>
	''' <param name="propItem"></param>
	''' <returns></returns>
	''' <remarks></remarks>
	Function FormatTagAscii(ByVal propItem As PropertyItem) As String
		Dim strRet As String
		Dim encoding As System.Text.ASCIIEncoding = New System.Text.ASCIIEncoding()

		strRet = encoding.GetString(propItem.Value, 0, propItem.Len - 1)
		Return strRet
	End Function
	''' <summary>
	''' Format a Short tag (unsigned).
	''' </summary>
	''' <param name="propItem"></param>
	''' <returns></returns>
	''' <remarks></remarks>
	Function FormatTagShort(ByVal propItem As PropertyItem) As String
		Dim strRet As String = ""
		Dim i As Integer = 0

		Do While i < propItem.Len
			Dim val As System.UInt16 = BitConverter.ToUInt16(propItem.Value, i)
			strRet += val.ToString()
			If (i + BYTEJUMP_SHORT < propItem.Len) Then
				strRet += " "
			End If
			i += BYTEJUMP_SHORT
		Loop

		Return strRet
	End Function
	''' <summary>
	''' Format a Long tag (unsigned).
	''' </summary>
	''' <param name="propItem"></param>
	''' <returns></returns>
	''' <remarks></remarks>
	Function FormatTagLong(ByVal propItem As PropertyItem) As String
		Dim strRet As String = ""
		Dim i As Integer = 0

		Do While i < propItem.Len
			Dim val As System.UInt32 = BitConverter.ToUInt32(propItem.Value, i)
			strRet += val.ToString()
			If (i + BYTEJUMP_LONG < propItem.Len) Then
				strRet += " "
			End If
			i = i + BYTEJUMP_LONG
		Loop

		Return strRet
	End Function
	''' <summary>
	''' Format a Rational tag (unsigned).
	''' </summary>
	''' <param name="propItem"></param>
	''' <param name="formatInstr"></param>
	''' <returns></returns>
	''' <remarks></remarks>
	Function FormatTagRational(ByVal propItem As PropertyItem, ByVal formatInstr As FormatInstr) As String
		Dim strRet As String = ""
		Dim i As Integer = 0

		Do While i < propItem.Len
			Dim numer As System.UInt32 = BitConverter.ToUInt32(propItem.Value, i)
			Dim denom As System.UInt32 = BitConverter.ToUInt32(propItem.Value, i + ByteJump_Long)

			Console.WriteLine("NUMER: " & numer & " | DENOM: " & denom)

			If formatInstr = formatInstr.Fraction Then
				Dim frac As UFraction = New UFraction(numer, denom)
				strRet += frac.ToString()
			Else
				Dim dbl As Double
				If (denom = 0) Then
					dbl = 0.0
				Else
					dbl = CDbl(numer) / CDbl(denom)
					strRet += dbl.ToString(DoubleType_Format)
				End If
			End If

			If (i + ByteJump_Rational < propItem.Len) Then
				strRet += " "
			End If
			i = i + ByteJump_Rational
		Loop
		Console.WriteLine(" | RESULT: " & strRet)
		Return strRet
	End Function
	''' <summary>
	''' Format a Undefined tag
	''' </summary>
	''' <param name="propItem"></param>
	''' <param name="formatInstr"></param>
	''' <returns></returns>
	''' <remarks></remarks>
	Function FormatTagUndefined(ByVal propItem As PropertyItem, ByVal formatInstr As FormatInstr) As String
		Dim strRet As String
		If formatInstr = formatInstr.AllChar Then
			Dim encoding As System.Text.ASCIIEncoding = New System.Text.ASCIIEncoding()
			strRet = encoding.GetString(propItem.Value, 0, propItem.Len)
		Else
			strRet = BitConverter.ToString(propItem.Value, 0, propItem.Len)

			'TODO check this
			'strRet = hexToString(strRet)
		End If
		Return strRet
	End Function
	''' <summary>
	''' Format a SLong tag (signed).
	''' </summary>
	''' <param name="propItem"></param>
	''' <param name="formatInstr"></param>
	''' <returns></returns>
	''' <remarks></remarks>
	Function FormatTagSLong(ByVal propItem As PropertyItem, ByVal formatInstr As FormatInstr) As String
		Dim strRet As String = ""
		Dim i As Integer = 0

		Do While i < propItem.Len
			Dim val As System.Int32 = BitConverter.ToInt32(propItem.Value, i)
			strRet += val.ToString()
			If (i + ByteJump_SLong < propItem.Len) Then
				strRet += " "
			End If
			i = i + ByteJump_SLong
		Loop
		Return strRet
	End Function
	''' <summary>
	''' Format a SRational tag (signed).
	''' </summary>
	''' <param name="propItem"></param>
	''' <param name="formatInstr"></param>
	''' <returns></returns>
	''' <remarks></remarks>
	Function FormatTagSRational(ByVal propItem As PropertyItem, ByVal formatInstr As FormatInstr) As String
		Dim strRet As String = ""
		Dim i As Integer = 0

		Do While i < propItem.Len
			'For i As Integer = 0 To i < propItem.Len
			Dim numer As System.Int32 = BitConverter.ToInt32(propItem.Value, i)
			Dim denom As System.Int32 = BitConverter.ToInt32(propItem.Value, i + ByteJump_SLong)
			If (formatInstr = formatInstr.Fraction) Then
				Dim frac As FractionManipulator = New FractionManipulator(numer, denom)
				strRet += frac.ToString()
			Else
				Dim dbl As Double
				If (denom = 0) Then
					dbl = 0.0
				Else
					dbl = CDbl(numer) / CDbl(denom)
					strRet += dbl.ToString(DoubleType_Format)
				End If
			End If
			If (i + ByteJump_SRational < propItem.Len) Then
				strRet += " "
			End If
			i = i + ByteJump_SRational
		Loop
		Return strRet
	End Function
End Class